package com.hmjk.health.home;

import org.json.JSONException;
import org.json.JSONObject;

import com.hmjk.health.HealthApp;
import com.hmjk.health.R;
import com.hmjk.health.background.NetService;
import com.hmjk.health.util.OnFragmentEventCallback;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.Html;
import android.text.InputType;
import android.text.TextWatcher;
import android.text.format.Time;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.NumberKeyListener;
import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class SignUpFragment extends Fragment implements OnClickListener, OnTouchListener, OnCheckedChangeListener, OnFocusChangeListener{
	private final String TAG = SignUpFragment.class.getSimpleName(); 
	
	private HealthApp mApp = null;
	private OnFragmentEventCallback mCallback;
	private EditText mUser;
	private EditText mPhone;
	private EditText mCode;
	private ImageView mCheckCode;
	private EditText mPassword;
	private EditText mConfirm;
	private TextView mErrHint;
	private ImageView mCheckUser;
	private Button mGetCode;
	private Button mSignUp;
	private CheckBox mAgree;
	private ImageButton mSee;
	private Animation cycleAnim;
	private boolean attached = false;
	
	private enum CHECK{
		NONE,
		CHECKING,
		OK,
		FAILED,
		TIMEOUT
	};
	
	private String sUser;
	private CHECK userCheckFlag = CHECK.NONE;
	
	private String sPhone;
	private CHECK phoneCheckFlag = CHECK.NONE;
	
	//private String identifyCode;
	
	private void logd(String info){
		Log.d(TAG,info);
	}
	
	@Override
	public void onAttach(Activity activity){
		logd("onAttach");
		super.onAttach(activity);
		mApp = (HealthApp)activity.getApplication();
		try{
			mCallback = (OnFragmentEventCallback)activity;
			attached = true;
		}catch(ClassCastException e){
			throw new ClassCastException(activity.getClass().getName() + " must implement OnFragmentEventCallback");
		}
	}
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
		logd("onCreateView");
		
		View v = inflater.inflate(R.layout.signup_fragment, container, false);
		
		cycleAnim = AnimationUtils.loadAnimation(getActivity(), R.anim.rotatecycled);
		TextView agreement = (TextView)v.findViewById(R.id.agreement);
		String str = getResources().getString(R.string.agreement);
		agreement.setText(Html.fromHtml(str));
		agreement.setOnClickListener(this);
		
		ImageButton back = (ImageButton)v.findViewById(R.id.back);
		back.setOnClickListener(this);
		
		mErrHint = (TextView)v.findViewById(R.id.err_hint);
		mErrHint.setVisibility(View.INVISIBLE);
		
		/* user */
		mUser = (EditText)v.findViewById(R.id.useredit);
		mUser.setText("");
		mUser.setKeyListener(new NumberKeyListener(){

			@Override
			public int getInputType() {
				return InputType.TYPE_CLASS_TEXT;
			}

			@Override
			protected char[] getAcceptedChars() {
				char[] allow = mApp.getAllowedChars("UserName");
				return allow;
			}
			
		});
		mUser.setOnFocusChangeListener(this);
		sUser = null;
		mCheckUser = (ImageView)v.findViewById(R.id.checkname);
		mCheckUser.setVisibility(View.INVISIBLE);
		userCheckFlag = CHECK.NONE;
		
		/*phone*/
		mPhone = (EditText)v.findViewById(R.id.numberedit);
		mPhone.setText("");
		sPhone = null;
		mPhone.setOnFocusChangeListener(this);
		mPhone.addTextChangedListener(new TextWatcher(){

			@Override
			public void afterTextChanged(Editable e) {
				if(phoneCheckFlag == CHECK.CHECKING)
					return;
				
				String p = e.toString().trim();
				if((p != null) && (p.length() >= 11)){
					mGetCode.setEnabled(true);
				}else{
					mGetCode.setEnabled(false);
				}
				
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start,int count, int after) {}

			@Override
			public void onTextChanged(CharSequence s, int start, int before,int count) {}
			
		});
		mGetCode = (Button)v.findViewById(R.id.getCode);
		mGetCode.setText(R.string.getcode);
		mGetCode.setOnClickListener(this);
		mGetCode.setEnabled(false);
		phoneCheckFlag = CHECK.NONE;
		
		/*identify code*/
		mCode = (EditText)v.findViewById(R.id.codeedit);
		mCode.setOnFocusChangeListener(this);
		mCode.setText("");
		/*mCode.addTextChangedListener(new TextWatcher(){
			@Override
			public void afterTextChanged(Editable e) {
				String p = e.toString().trim();
				if((p != null) && (p.length() == 6)){
					if((identifyCode != null) && identifyCode.equals(p))
						mCheckCode.setImageResource(R.drawable.tick);
					else
						mCheckCode.setImageResource(R.drawable.cross);
					mCheckCode.setVisibility(View.VISIBLE);
				}else{
					mCheckCode.setVisibility(View.INVISIBLE);
				}
				
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start,int count, int after) {}

			@Override
			public void onTextChanged(CharSequence s, int start, int before,int count) {}
			
		});*/
		mCheckCode = (ImageView)v.findViewById(R.id.checkcode);
		mCheckCode.setVisibility(View.INVISIBLE);
		//identifyCode = mApp.getSavedIdentifyCode();
		
		/*password*/
		mPassword = (EditText)v.findViewById(R.id.pwdedit);
		mPassword.setText("");
		mPassword.setOnFocusChangeListener(this);
		mPassword.setKeyListener(new NumberKeyListener(){

			@Override
			public int getInputType() {
				return InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD;
			}

			@Override
			protected char[] getAcceptedChars() {
				char[] allow = mApp.getAllowedChars("Password");
				return allow;
			}
			
		});
		mSee = (ImageButton)v.findViewById(R.id.see);
		mSee.setOnTouchListener(this);
		
		/*password confirm*/
		mConfirm = (EditText)v.findViewById(R.id.pwdcnfedit);
		mConfirm.setText("");
		mConfirm.setOnFocusChangeListener(this);
		mConfirm.setKeyListener(new NumberKeyListener(){

			@Override
			public int getInputType() {
				return InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD;
			}

			@Override
			protected char[] getAcceptedChars() {
				char[] allow = mApp.getAllowedChars("Password");
				return allow;
			}
			
		});
		
		mAgree = (CheckBox)v.findViewById(R.id.agree);
		mAgree.setOnCheckedChangeListener(this);
		
		mSignUp = (Button)v.findViewById(R.id.signup_but);
		mSignUp.setOnClickListener(this);
		attached = true;
		return v;
	}
	
	private void reset(){
		if(mErrHint == null)
			return;
		
		mErrHint.setVisibility(View.INVISIBLE);
		mUser.setText("");
		mCheckUser.setVisibility(View.INVISIBLE);
		userCheckFlag = CHECK.NONE;
		mPhone.setText("");
		mGetCode.setText(R.string.getcode);
		mGetCode.setEnabled(false);
		phoneCheckFlag = CHECK.NONE;
		mCode.setText("");
		mCheckCode.setVisibility(View.INVISIBLE);
		mPassword.setText("");
		mConfirm.setText("");
		mAgree.setChecked(true);
	}
	
	@Override
	public void onDetach(){
		attached = false;
		super.onDetach();
		logd("onDetach");
	}
	
	@Override
	public void onDestroyView(){
		attached = false;
		mHandler.removeMessages(MSG_IDENTIFY_CODE_COUNTDOWN);
		super.onDestroyView();
		logd("onDestroyView");
	}
	
	private void checkUser(){
		String u = mUser.getText().toString().trim();
		if((u != null) && (u.isEmpty() == false)){
			if((sUser == null) || (sUser.equals(u) == false)){
				Intent si = new Intent(getActivity(), NetService.class);
				si.setAction(NetService.VALIDATE_USER_ACCOUNT);
				si.putExtra("account", u);
				Time t = new Time();
				t.setToNow();
				String stamp = "VALIDATE_USER_ACCOUNT" + t.toString(); 
				si.putExtra("stamp",stamp);
				mApp.addNetHandler(stamp,mHandler);
				getActivity().startService(si);
				
				userCheckFlag = CHECK.CHECKING;
				mCheckUser.setVisibility(View.VISIBLE);
				mCheckUser.setImageResource(R.drawable.wait_small);
				mCheckUser.startAnimation(cycleAnim);
				mUser.setEnabled(false);
			}
		}else{
			sUser = null;
			userCheckFlag = CHECK.NONE;
		}
	}
	
	private void updateErrorHint(int resid){
		mErrHint.setVisibility(View.VISIBLE);
		mErrHint.setText(resid);
	}
	
	
	private void overrideErrorHint(){
		mErrHint.setVisibility(View.INVISIBLE);
		
	}

	@Override
	public void onClick(View v) {
		switch(v.getId()){
		case R.id.back:{
			mCallback.onEvent(SignInActivity.ACT_BACK_TO_SIGNIN, null);
		}
		break;
		case R.id.agreement:{
			mCallback.onEvent(SignInActivity.ACT_SHOW_AGREEMENT, null);
		}
		break;
		case R.id.signup_but:{
			if(mApp.checkNetwork() == false){
				mApp.vibrate();
				break;
			}
			
			String u = mUser.getText().toString().trim();
			if((u == null) || u.isEmpty()){
				updateErrorHint(R.string.Account_empty);
				break;
			}
			if((sUser == null) || (sUser.equals(u) == false)){
				checkUser();
				break;
			}
			
			if(userCheckFlag != CHECK.OK){
				break;
			}
			
			String p = mPhone.getText().toString().trim();
			if((p == null) || p.isEmpty()){
				updateErrorHint(R.string.phone_empty);
				break;
			}
			
			String i = mCode.getText().toString().trim();
			if((i == null) || i.isEmpty() || i.length() < 6){
				updateErrorHint(R.string.idcode_invalid);
				break;
			}
			
			/*if((identifyCode == null) || (i.equals(identifyCode) == false)){
				updateErrorHint(R.string.idcode_invalid);
				break;
			}*/
			
			String pwd = mPassword.getText().toString().trim();
			String cnf = mConfirm.getText().toString().trim();
			if((pwd == null) || (pwd.length() < 6)){
				updateErrorHint(R.string.pwd_invalid);
				break;
			}
			if((cnf == null) || (cnf.equals(pwd) == false)){
				updateErrorHint(R.string.pwd_cnf_err);
				break;
			}
			
			mApp.showWaitting(getActivity(),null);
			
			Intent si = new Intent(getActivity(), NetService.class);
			si.setAction(NetService.SIGN_UP_NEW_ACCOUNT);
			si.putExtra("phone", p);
			si.putExtra("user", u);
			si.putExtra("password", pwd);
			si.putExtra("idcode",i);
			Time t = new Time();
			t.setToNow();
			String stamp = "SIGN_UP_NEW_ACCOUNT" + t.toString(); 
			si.putExtra("stamp",stamp);
			mApp.addNetHandler(stamp,mHandler);
			getActivity().startService(si);
		}
		break;
		case R.id.getCode:{
			if(mApp.checkNetwork() == false){
				mApp.vibrate();
				break;
			}
			String p = mPhone.getText().toString().trim();
			if((p == null) || p.isEmpty() || (p.length() < 11)){
				sPhone = null;
				break;
			}
			
			Intent si = new Intent(getActivity(), NetService.class);
			si.setAction(NetService.GET_IDENTIFY_CODE);
			si.putExtra("phone", p);
			Time t = new Time();
			t.setToNow();
			String stamp = "GET_IDENTIFY_CODE" + t.toString(); 
			si.putExtra("stamp",stamp);
			mApp.addNetHandler(stamp,mHandler);
			getActivity().startService(si);
			phoneCheckFlag = CHECK.CHECKING;
			mPhone.setEnabled(false);
			mGetCode.setEnabled(false);
			mGetCode.setText(R.string.idcode_getting);
		}
		break;
		}
		
	}

	@Override
	public boolean onTouch(View v, MotionEvent e) {
		if(v.getId() == R.id.see){
			
			if(e.getAction() == MotionEvent.ACTION_DOWN){
				//see pwd
				int pos = mPassword.getSelectionStart();
				mPassword.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
				mPassword.setSelection(pos);
			}else if((e.getAction() == MotionEvent.ACTION_UP) ||
					(e.getAction() == MotionEvent.ACTION_CANCEL)){
				//hide pwd
				int pos = mPassword.getSelectionStart();
				mPassword.setTransformationMethod(PasswordTransformationMethod.getInstance());
				mPassword.setSelection(pos);
			}
		}
		return false;
	}

	@Override
	public void onCheckedChanged(CompoundButton v, boolean checked) {
		if(v.getId() == R.id.agree){
			mSignUp.setEnabled(checked);
		}
	}

	@Override
	public void onFocusChange(View v, boolean focused) {
		if(mApp.checkNetwork() == false){
			//mApp.vibrate();
			return;
		}
		

		overrideErrorHint();
		
		switch(v.getId()){
		case R.id.useredit:{
			if(focused == false){
				checkUser();
			}
		}
		break;
		
		}
		
	}
	
	private Toast mToast = null;
	private void showToast(int resid){
		if(mToast != null){
			mToast.cancel();
		}
		mToast = Toast.makeText(getActivity(), resid, Toast.LENGTH_LONG);	
		mToast.show();
	}
	
	private static final int MSG_IDENTIFY_CODE_COUNTDOWN = 201;
	
	private Handler mHandler = new Handler(){
		@Override
		public void handleMessage(Message msg){
			if(!attached)
				return;
			
			switch(msg.what){
			case MSG_IDENTIFY_CODE_COUNTDOWN:{
				Bundle b = msg.getData();
				int count = b.getInt("count");
				count--;
				if(count >= 0){
					String h = getResources().getString(R.string.getcodeafter,count);
					mGetCode.setText(h);
					mGetCode.setEnabled(false);
					Message mm = mHandler.obtainMessage(MSG_IDENTIFY_CODE_COUNTDOWN);
					
					b.putInt("count", count);
					mm.setData(b);
					mHandler.sendMessageDelayed(mm, 1000);
				}else{
					mGetCode.setText(R.string.getcode);
					mGetCode.setEnabled(true);
				}
			}
			break;
			case HealthApp.MSG_NET_RESPONSE:{
				Bundle b = msg.getData();
				String stamp = b.getString("stamp","ooh!No!");
				boolean canceled = b.getBoolean("canceled", false);
				if(stamp.startsWith("VALIDATE_USER_ACCOUNT")){
					String sjson = b.getString("json");
					if(sjson != null){
						try {
							JSONObject json = new JSONObject(sjson);
							int code = json.getInt("code");
							if(code == 200){
								String state = json.getString("state");
								mUser.setEnabled(true);
								sUser = mUser.getText().toString().trim();
								if(state.equals("00")){
									userCheckFlag = CHECK.OK;
									mCheckUser.setVisibility(View.VISIBLE);
									mCheckUser.clearAnimation();
									mCheckUser.setImageResource(R.drawable.tick);
									break;
								}else if(state.equals("01")){
									userCheckFlag = CHECK.FAILED;
									mCheckUser.setVisibility(View.VISIBLE);
									mCheckUser.clearAnimation();
									mCheckUser.setImageResource(R.drawable.cross);
									updateErrorHint(R.string.server_noResp);
									sUser = null;
									break;
								}else if(state.equalsIgnoreCase("0B")){
									userCheckFlag = CHECK.FAILED;
									mCheckUser.setVisibility(View.VISIBLE);
									mCheckUser.clearAnimation();
									mCheckUser.setImageResource(R.drawable.cross);
									updateErrorHint(R.string.checkAccout_exist);
									break;
								}
							}
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} 
					}
					mUser.setEnabled(true);
					mCheckUser.setVisibility(View.VISIBLE);
					mCheckUser.clearAnimation();
					mCheckUser.setImageResource(R.drawable.cross);
					userCheckFlag = CHECK.FAILED;
					sUser = null;
					updateErrorHint(R.string.checkAccout_failed);
				}else if(stamp.startsWith("GET_IDENTIFY_CODE")){
					String sjson = b.getString("json");
					if(sjson != null){
						try {
							JSONObject json = new JSONObject(sjson);
							int code = json.getInt("code");
							if(code == 200){
								String state = json.getString("state");
								mPhone.setEnabled(true);
								sPhone = mPhone.getText().toString().trim();
								if(state.equals("00")){
									phoneCheckFlag = CHECK.OK;
									//identifyCode = mApp.getSavedIdentifyCode();
									String h = getResources().getString(R.string.getcodeafter,60);
									mGetCode.setText(h);
									mGetCode.setEnabled(false);
									showToast(R.string.sendIdentifyCodeHint);
									Message mm = mHandler.obtainMessage(MSG_IDENTIFY_CODE_COUNTDOWN);
									Bundle b1 = new Bundle();
									b1.putInt("count", 60);
									mm.setData(b1);
									mHandler.sendMessageDelayed(mm, 1000);
									break;
								}else if(state.equals("01")){
									phoneCheckFlag = CHECK.FAILED;
									updateErrorHint(R.string.server_noResp);
									sPhone = null;
									mGetCode.setText(R.string.getcode);
									mGetCode.setEnabled(true);
									break;
								}else if(state.equalsIgnoreCase("0A")){
									phoneCheckFlag = CHECK.FAILED;
									updateErrorHint(R.string.getLater);
									showToast(R.string.getLater);
									sPhone = null;
									mGetCode.setText(R.string.getcode);
									mGetCode.setEnabled(true);
									break;
								}else if(state.equalsIgnoreCase("0B")){
									phoneCheckFlag = CHECK.FAILED;
									updateErrorHint(R.string.checkPhone_exist);
									mGetCode.setText(R.string.getcode);
									mGetCode.setEnabled(true);
									sPhone = null;
									break;
								}else if(state.equalsIgnoreCase("25")){
									phoneCheckFlag = CHECK.FAILED;
									updateErrorHint(R.string.get_idcode_failed);
									mGetCode.setText(R.string.getcode);
									mGetCode.setEnabled(true);
									sPhone = null;
									break;
								}
							}
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} 
					}
					mPhone.setEnabled(true);
					phoneCheckFlag = CHECK.FAILED;
					sPhone = null;
					updateErrorHint(R.string.checkPhone_failed);
					mGetCode.setText(R.string.getcode);
					mGetCode.setEnabled(true);
				}else if(stamp.startsWith("SIGN_UP_NEW_ACCOUNT")){
					String sjson = b.getString("json");
					mApp.dismissWaiting();
					if(sjson != null){
						try {
							JSONObject json = new JSONObject(sjson);
							int code = json.getInt("code");
							if(code == 200){
								String state = json.getString("state");
								if(state.equals("00")){
									mToast = Toast.makeText(getActivity(), R.string.signUpOk, Toast.LENGTH_SHORT);	
									mToast.show();
									reset();
									mCallback.onEvent(SignInActivity.ACT_BACK_TO_SIGNIN, sUser);
								}
							}
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
			}
			break;
			}
		}
	};
}
